package com.lanzuo.adapter.common.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.IOException;
import java.util.*;

public class LooseJsonComparator {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 比较两个 JSON 字符串是否相等（忽略字段顺序和数组顺序）
     */
    public static boolean equalsLoose(String json1, String json2) {
        try {
            JsonNode tree1 = objectMapper.readTree(json1);
            JsonNode tree2 = objectMapper.readTree(json2);
            return deepEqualsLoose(tree1, tree2);
        } catch (IOException e) {
            throw new IllegalArgumentException("Invalid JSON", e);
        }
    }

    /**
     * 递归比较两个 JsonNode（宽松模式）
     */
    private static boolean deepEqualsLoose(JsonNode n1, JsonNode n2) {
        if (n1 == null || n2 == null) {
            return n1 == n2;
        }

        if (!n1.getNodeType().equals(n2.getNodeType())) {
            return false;
        }

        switch (n1.getNodeType()) {
            case OBJECT:
                return compareObjects((ObjectNode) n1, (ObjectNode) n2);
            case ARRAY:
                return compareArrays((ArrayNode) n1, (ArrayNode) n2);
            case STRING:
            case NUMBER:
            case BOOLEAN:
            case NULL:
                return n1.equals(n2); // 基本类型直接比较
            default:
                return n1.equals(n2);
        }
    }

    /**
     * 比较两个 JSON 对象（忽略字段顺序）
     */
    private static boolean compareObjects(ObjectNode o1, ObjectNode o2) {
        if (o1.size() != o2.size()) {
            return false;
        }

        Iterator<String> fieldNames = o1.fieldNames();
        while (fieldNames.hasNext()) {
            String fieldName = fieldNames.next();
            if (!o2.has(fieldName)) {
                return false;
            }
            if (!deepEqualsLoose(o1.get(fieldName), o2.get(fieldName))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 比较两个 JSON 数组（忽略元素顺序）
     */
    private static boolean compareArrays(ArrayNode a1, ArrayNode a2) {
        if (a1.size() != a2.size()) {
            return false;
        }

        // 将数组元素转为可排序的列表
        List<JsonNode> list1 = new ArrayList<>();
        List<JsonNode> list2 = new ArrayList<>();

        a1.elements().forEachRemaining(list1::add);
        a2.elements().forEachRemaining(list2::add);

        // 尝试排序（仅当元素可比较时）
        try {
            // 使用自定义比较器对 JsonNode 排序（基于序列化字符串）
            Comparator<JsonNode> nodeComparator = (n1, n2) -> {
                String s1 = n1.toString();
                String s2 = n2.toString();
                return s1.compareTo(s2);
            };

            list1.sort(nodeComparator);
            list2.sort(nodeComparator);
        } catch (Exception e) {
            // 如果排序失败（如含不可比对象），回退到多重集合比较
            return multisetEquals(list1, list2);
        }

        // 逐个比较排序后的元素
        for (int i = 0; i < list1.size(); i++) {
            if (!deepEqualsLoose(list1.get(i), list2.get(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 回退方案：使用多重集合（Multiset）比较（不依赖排序）
     */
    private static boolean multisetEquals(List<JsonNode> list1, List<JsonNode> list2) {
        if (list1.size() != list2.size()) return false;

        // 统计每个元素出现次数（用 toString 作为 key）
        Map<String, Integer> count1 = new HashMap<>();
        Map<String, Integer> count2 = new HashMap<>();

        for (JsonNode node : list1) {
            String key = node.toString();
            count1.put(key, count1.getOrDefault(key, 0) + 1);
        }
        for (JsonNode node : list2) {
            String key = node.toString();
            count2.put(key, count2.getOrDefault(key, 0) + 1);
        }

        return count1.equals(count2);
    }

    // ===== 示例测试 =====
    public static void main(String[] args) {
        String json1 = "{ \"name\": \"Alice\", \"tags\": [\"java\", \"dev\"], \"info\": { \"age\": 30, \"city\": \"BJ\" } }";
        String json2 = "{ \"tags\": [\"dev\", \"java\"], \"info\": { \"city\": \"BJ\", \"age\": 30 }, \"name\": \"Alice\" }";
        String json3 = "{ \"name\": \"Alice\", \"tags\": [\"dev\"], \"info\": { \"age\": 30, \"city\": \"BJ\" } }";

        String old = "[{\"PcsNum\":\"P05.68.026737.0003202508140600434004\",\"PcsSn\":\"1\"},{\"PcsNum\":\"P05.68.026737.0003202508140600434005\",\"PcsSn\":\"2\"},{\"PcsNum\":\"P05.68.026737.0003202508140600434006\",\"PcsSn\":\"3\"},{\"PcsNum\":\"P05.68.026737.0003202508140600434003\",\"PcsSn\":\"4\"},{\"PcsNum\":\"P05.68.026737.0003202508140600434002\",\"PcsSn\":\"5\"},{\"PcsNum\":\"P05.68.026737.0003202508140600434001\",\"PcsSn\":\"6\"}]";
        String newJson = "[{\"PcsNum\":\"P05.68.026737.0003202508140600458004\",\"PcsSn\":\"1\"},{\"PcsNum\":\"P05.68.026737.0003202508140600458005\",\"PcsSn\":\"2\"},{\"PcsNum\":\"P05.68.026737.0003202508140600458006\",\"PcsSn\":\"3\"},{\"PcsNum\":\"P05.68.026737.0003202508140600458003\",\"PcsSn\":\"4\"},{\"PcsNum\":\"P05.68.026737.0003202508140600458002\",\"PcsSn\":\"5\"},{\"PcsNum\":\"P05.68.026737.0003202508140600458001\",\"PcsSn\":\"6\"}]";

        System.out.println(equalsLoose(json1, json2)); // true
        System.out.println(equalsLoose(json1, json3)); // false

        // 测试嵌套数组
        String arr1 = "{ \"data\": [ {\"id\":2}, {\"id\":1} ] }";
        String arr2 = "{ \"data\": [ {\"id\":1}, {\"id\":2} ] }";
        System.out.println(equalsLoose(arr1, arr2)); // true
    }
}